package org.wrigut.scanlib;

/* TransitionFunction.java
 * 
 * Project 1 - CS 3361
 * 
 * Authors: Chris Gutierrez
 *          Jordan Wright
 */

public class TransitionFunction {
	private int[][] states;
	private int[] finalStates= {2,6,7,8,9,10,12,14,15,16};
	private TokenType[] tokenTypes;
	private String specialChars = "\n/*()+-:=.";
	
	public TransitionFunction() {
		//fill array
		states = new int[18][14];		
		int[] row1 = {17,17, 2,10, 6, 7, 8, 9,11, 0,13,14,16, 0};
		fillRow(0,row1);
		
		states[1][2] = 3;
		states[1][3] = 4;
		
		fillRow(2, 3);
		states[2][1] = 18;
		
		fillRow(3, 4);
		states[3][3] = 5;
		
		fillRow(4, 4);
		//end?
		states[4][2] = 18;
		states[4][3] = 5;
		
		states[10][9] = 12;
		
		states[12][11] = 15;
		
		states[13][10] = 15;
		states[13][11] = 14;
		
		states[14][11] = 15;
		
		states[15][11] = 16;
		states[15][12] = 16;
		
		states[16][0] = 17;
		states[16][1] = 17;
		
		//TokenTypes
		tokenTypes = new TokenType[18];
        tokenTypes[1]=TokenType.div;
        tokenTypes[5]=TokenType.lparen;
        tokenTypes[6]=TokenType.rparen;
        tokenTypes[7]=TokenType.plus;
        tokenTypes[8]=TokenType.minus;
        tokenTypes[9]=TokenType.times;
        tokenTypes[11]=TokenType.assign;
        tokenTypes[13]=TokenType.number;
        tokenTypes[14]=TokenType.number;
        tokenTypes[15]=TokenType.id;
	}
	
	private void fillRow(int rowIndex, int[] row) {
		for (int i = 0; i < row.length; i++) {
			states[rowIndex][i] = row[i];
		}
	}
	
	private void fillRow(int row, int fill) {
		for (int i = 0; i < states[0].length; i++) {
			states[row][i] = fill;
		}
	}
	
	//This function translates a character to its corresponding column index
	//at the state transition table
	private int getIndex(char c) {
		if (c == ' ' || c == '\t') {
			return 0;
		}
		int i = specialChars.indexOf(c);
		if (i != -1) {
			return i+1;
		}
		if (Character.isDigit(c)) {
			return 11;
		}
		if (Character.isLetter(c)) {
			return 12;
		}
		return 13;
	}
	
	//This function represents a step in the scanner automaton:
	//It takes a state and a label as input
	//It returns the state the automaton follows in the given case
	public int nextState(int state, char label) {
		return states[state-1][getIndex(label)];
	}
	
	//Checks to see if the state sent as argument is a final state
    public boolean isFinal(int state)
    {
        boolean tf = false;
        for(int i=0;i<this.finalStates.length;i++)
        {
            if(this.finalStates[i]==state)
            {
                tf = true;
                break;
            }
        }
        return tf;
    }
    
    public TokenType getTokenType(int state) {
    	return tokenTypes[state-1];
    }
}
